home *** CD-ROM | disk | FTP | other *** search
- /*
- * eh_seg.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /*
- * ** E(xtract) H(istograms)_SEG
- * **
- * ** routine to extract desired set of parameters from a data file of
- * ** type .SEG whose name is entered as a command line argument and
- * ** construct a histogram; write output file of type *.hdt to be read
- * ** by routine hf.c
- * **
- */
- #include "eh_seg.h"
-
- #define MAX_REC_SIZE 1200
-
- #define BIN_NUMBER 10 /* no bins in histogram */
- #define LEN_HIST "\nhistogram for segment length"
- #define ANGLE_HIST "\nhistogram for segment turn angles"
-
- #define ON 1
- #define OFF 0
-
- #undef SHOW_ANG
- #undef SHOW_SORT
- #define DBG_ANG
-
-
- /*
- * ** global variables
- */
- extern char *optarg;
- extern int optind, opterr;
-
-
- static char *HIST_HEADER;
- int N_BINS = BIN_NUMBER;
- int MIN_SET = 0;
- int MAX_SET = 0;
- int WRITE_FILE = 0;
- int SHOW_INPUT = 0;
- int A_HIST = 0;
- int L_HIST = 0;
-
- /*
- * usage of routine
- */
- void
- usage (char *progname)
- {
- progname = last_bs (progname);
- printf ("USAGE: %s infile [-s] [-a] [-l] [-n n] [-i f] [-f f] [-w] [-L]\n", progname);
- printf ("\n%s extracts histogram data from infile (SEG), generated by\n", progname);
- printf ("fitpolyg, containing line segment data\n\n");
- printf ("ARGUMENTS:\n");
- printf (" infile: input filename (SEG)\n\n");
- printf ("OPTIONS:\n");
- printf (" -s: show input data\n\n");
- printf (" construct histogram for:\n");
- printf (" -a: turn angles between consecutive segments\n");
- printf (" -l: histogram of segment lengths\n");
- printf (" -n n: set number of bins to n (default: 10)\n");
- printf (" -i f: set initial value to (float)f (default: MIN)\n");
- printf (" -f f: set final value to (float)f (default: MAX)\n");
- printf (" -w: write output file of type .hdt (hist data)\n");
- exit (1);
- }
-
-
-
- /*
- * ** comparison function for qsort():
- * ** sort array of tuples in order of increassing x-values
- */
- int
- compare (t1, t2)
- float *t1, *t2;
- {
- return ((int) SIGN (*t1 - *t2));
- }
-
-
- /*
- * ** determine mean of input data set
- */
- double
- find_mean (float *data, int n)
- {
- int i;
- double mean = 0.0;
-
- for (i = 0; i < n; i++)
- mean += *(data + i);
-
- return (mean / (double) n);
- }
-
- /*
- * ** determine standard deviation of input data set
- */
- double
- find_sigma (float *data, int n, double mean)
- {
- int i;
- double xi, sigma = 0.0;
-
- for (i = 0; i < n; i++) {
- xi = (double) (*(data + i));
- sigma += (xi - mean) * (xi - mean);
- }
- sigma /= (double) (n - 1);
-
- return (sqrt (sigma));
- }
-
-
- /*
- * ** construct histogram of input data
- */
- void
- construct_hist (int n, float *data, float *hist, double bw, double data_base)
- {
- int i, ibin;
-
- for (i = 0; i < n; i++) {
- if (*(data + i) != 0) {
- ibin = 0;
- while (*(data + i) >= data_base + ibin * bw)
- ibin++;
- *(hist + ibin - 1) += 1;
- }
- }
- }
-
-
-
- /*
- * ** read first line in data file to determine size of record
- */
- int
- seg_size (FILE * file)
- {
- int retval;
- int n_rec;
-
- if (((retval = fscanf (file, "%d", &n_rec)) == 0) || (retval == EOF)) {
- printf ("wrong input file format!\n");
- exit (1);
- }
- return (n_rec);
- }
-
-
- #define LOLIM 0.01
- #define UPLIM 200.0
-
- /*
- * ** decode given slope, tan PHI, and return signed angle PHI (in rad);
- * ** sign convention: CCW <--> pos, counting from pos. x-direction
- */
- double
- slp_to_angle (double m, double delx, double dely)
- {
- double phi = -5.0;
-
- #ifdef DEBUG
- printf ("SLP_TO_ANGLE:...m = %lf, delx = %lf, dely = %lf\n",
- m, delx, dely);
- #endif
-
- if (fabs (m) < LOLIM) { /* horizontal segm */
- if (SIGN (delx) > 0)
- phi = 0.0;
- else if (SIGN (delx) < 0)
- phi = PI;
- else
- phi = -7.0;
- }
- else if (fabs (m) > UPLIM) { /* vertical segm */
- if (SIGN (dely) < 0)
- phi = 0.5 * PI;
- else if (SIGN (dely) > 0)
- phi = 1.5 * PI;
- else
- phi = -8.0;
- }
- else {
- if (SIGN (delx) > 0) {
- if (SIGN (dely) > 0)
- phi = atan (m);
- if (SIGN (dely) < 0)
- phi = 2.0 * PI + atan (m);
- }
- else if (SIGN (delx) < 0) {
- if (SIGN (dely) > 0)
- phi = PI + atan (m);
- if (SIGN (dely) < 0)
- phi = PI + atan (m);
- }
- else
- phi = -9.0;
- }
-
- if (fabs (phi) > 2.0 * PI) {
- printf ("\nSLP_TO_AN:...ill defined condition encountered:");
- printf (" m = %lf, phi = %lf\n", m, phi);
- phi = 0.0;
- return (phi);
- }
-
- #ifdef DEBUG
- printf (" value to be returned: %8.4lf\n", phi);
- #endif
-
- return (phi);
- }
-
-
- /*
- * ** read segment data from formatted data file (generally of type .seg)
- * ** written by pcctoseg.c; first column contains segment index: must not
- * ** exceed 9999!!
- */
- void
- get_seg_data (fp, n_segm, segm)
- FILE *fp;
- int n_segm;
- struct Segm *segm;
- {
- int i;
- int retval;
-
- for (i = 0; i < n_segm; i++) {
- retval = fscanf (fp, "%4d %3d %3d %3d %3d %f %3d",
- &((segm + i)->segm_ind),
- &((segm + i)->ptO.x), &((segm + i)->ptO.y),
- &((segm + i)->ptF.x), &((segm + i)->ptF.y),
- &((segm + i)->slope), &((segm + i)->line_ind));
- }
- }
-
-
-
-
- void
- main (argc, argv)
- int argc;
- char *argv[];
- {
- int i_arg;
- int i, ich, is;
- int n_segm;
- static char wbuf[20];
- static char *inp_suffix =
- {".seg"}; /* default inp file suffix */
- static char *seg_type =
- {".seg"}; /* suffix for .sgl inp file */
- static char *wsuffix =
- {".hdt"}; /* suffix for output file name */
- char *rbuf;
-
- int n_parms = 3;
- double ndel_x, ndel_y, del_x, del_y;
- struct Segm *inSegm; /* sample input */
-
- int cur_ln_ind, next_ln_ind;
- float cur_slp, next_slp;
- double cur_th, next_th, del_th;
-
-
- float bin_width, min = (float) -1.0, max = (float) -1.0;
- float *data, *hist;
- double mean, std_dev;
- float one = (float) 1.0;
-
- FILE *fpIn, *fpOut;
-
- /*
- * ** cmd line options:
- */
- static char *optstring = "slan:i:f:wL";
-
-
- /*
- * ** parse command line
- */
- optind = 2;
- opterr = ON; /* give error messages */
-
-
- if (argc < 2)
- usage (argv[0]);
-
- while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
- switch (i_arg) {
- case 's':
- printf ("\n...option %c: ", i_arg);
- printf ("display input data\n");
- SHOW_INPUT = ON;
- break;
- case 'a':
- printf ("\n...option %c: ", i_arg);
- printf ("hist of turn angles betw consec segm\n");
- A_HIST = ON;
- break;
- case 'l':
- printf ("\n...option %c: ", i_arg);
- printf ("hist of segm lengths\n");
- L_HIST = ON;
- break;
- case 'n':
- printf ("\n...option %c: ", i_arg);
- printf ("set number of bins to %d\n",
- N_BINS = atoi (optarg));
- break;
- case 'i':
- printf ("\n...option %c: ", i_arg);
- printf ("set min (init value) to %f\n",
- min = (float) atof (optarg));
- MIN_SET = 1;
- break;
- case 'f':
- printf ("\n...option %c: ", i_arg);
- printf ("set max (final value) to %f\n",
- max = (float) atof (optarg));
- MAX_SET = 1;
- break;
- case 'w':
- printf ("\n...option %c: ", i_arg);
- printf ("write output to file %s\n", wbuf);
- WRITE_FILE = 1;
- break;
- case 'L':
- print_sos_lic ();
- exit (0);
- default:
- printf ("\n...unknown cmd line argument\n");
- exit (1);
- break;
- }
- }
- printf ("read sgl data from file %s\n", rbuf = argv[1]);
- /* open input file */
- if ((fpIn = fopen (rbuf, "r")) == NULL) {
- printf ("\n...cannot not open input file\n");
- exit (1);
- }
-
- /* initialize size variables */
- if ((n_segm = seg_size (fpIn)) > MAX_REC_SIZE) {
- printf ("\n...record size of %d exceeds limit of %d\n",
- n_segm, MAX_REC_SIZE);
- exit (1);
- }
-
- /* construct output file name */
- ich = 0;
- while ((*(wbuf + ich) = *(rbuf + ich)) != '.')
- ich++;
- for (is = 0; is < 4; is++)
- *(wbuf + (ich) + is) = *(wsuffix + is);
- /* strip input file suffix */
- for (is = 0; is < 4; is++)
- *(inp_suffix + is) = *(rbuf + (ich) + is);
- if (strcmp (inp_suffix, seg_type) != 0) {
- printf ("\n...unknown input file type encountered:");
- printf (" default: %s\n", seg_type);
- fclose (fpIn);
- exit (1);
- }
- if (WRITE_FILE) {
- if ((fpOut = fopen (wbuf, "w")) == NULL) {
- printf ("\n...cannot open %s for writing\n", wbuf);
- exit (1);
- }
- }
- if ((A_HIST == 0) && (L_HIST == 0)) {
- printf ("\n...must specify option -a or -l!!\n");
- exit (1);
- }
- if (A_HIST == 1) {
- if (min > max) {
- printf ("\n...delected min exceeds max!!\n");
- exit (1);
- }
- }
- printf ("...number of segments in file %s: %d\n", rbuf, n_segm);
-
-
- /*
- * ** allocate memory
- */
- if ((hist = (float *) calloc ((size_t) N_BINS, sizeof (float))) == NULL) {
- printf ("\nEH_SEG: mem alloc for hist failed\n");
- exit (1);
- }
- if ((inSegm = (struct Segm *) calloc ((size_t) n_segm, sizeof (struct Segm))) == NULL) {
- printf ("\nEH_SEG: mem alloc for inSegm failed\n");
- exit (1);
- }
- if ((data = (float *) calloc ((size_t) n_segm, sizeof (float))) == NULL) {
- printf ("\nEH_SEG: mem alloc for data failed\n");
- exit (1);
- }
-
- /*
- * ** fetch data
- */
- get_seg_data (fpIn, n_segm, inSegm);
-
- /*
- * ** write output
- */
- if (SHOW_INPUT == ON) {
- printf ("\n...input data:\n");
- for (i = 0; i < n_segm; i++) {
- printf ("%4d %3d %3d %3d %3d %f8.2 %4d\n",
- (inSegm + i)->segm_ind,
- (inSegm + i)->ptO.x, (inSegm + i)->ptO.y,
- (inSegm + i)->ptF.x, (inSegm + i)->ptF.y,
- (inSegm + i)->slope, (inSegm + i)->line_ind);
- }
- }
-
- /*
- * ** evaluate statistics and construct histogram
- */
- if (L_HIST == ON) {
- printf ("\n...evaluating histogram of segment lengths...\n");
- for (i = 0; i < n_segm; i++) {
- del_x = (double) ((inSegm + i)->ptF.x - (inSegm + i)->ptO.x);
- del_y = (double) ((inSegm + i)->ptF.y - (inSegm + i)->ptO.y);
- *(data + i) = (float) sqrt (del_x * del_x + del_y * del_y);
- }
- }
- else if (A_HIST == ON) {
- printf ("\n...evaluating histogram of turn angles...\n");
- i = 0;
- do {
-
- cur_ln_ind = (inSegm + i)->line_ind;
- #ifdef SHOW_ANG
- printf ("\nline_index: %4d\n", cur_ln_ind);
- #endif
-
- while ((next_ln_ind = (inSegm + i + 1)->line_ind) == cur_ln_ind) {
- #ifdef SHOW_ANG
- printf ("...segment pair:%4d %4d ",
- (inSegm + i)->segm_ind, (inSegm + i + 1)->segm_ind);
- #endif
- cur_slp = (inSegm + i)->slope;
- del_x = (double) ((inSegm + i)->ptF.x - (inSegm + i)->ptO.x);
- del_y = (double) ((inSegm + i)->ptF.y - (inSegm + i)->ptO.y);
- next_slp = (inSegm + i + 1)->slope;
- ndel_x = (double) ((inSegm + i + 1)->ptF.x - (inSegm + i + 1)->ptO.x);
- ndel_y = (double) ((inSegm + i + 1)->ptF.y - (inSegm + i + 1)->ptO.y);
-
- /* angle conv: CCW <--> positive */
- if (cur_slp * next_slp == -1.0) {
- printf ("\n...segments perpendicular...\n");
- if (cur_slp > 0.0) {
- if (del_x > 0.0) {
- if (ndel_x > 0.0)
- *(data + i) = (float) 90.0;
- if (ndel_x < 0.0)
- *(data + i) = (float) -90.0;
- }
- else if (del_x < 0.0) {
- if (ndel_x > 0.0)
- *(data + i) = (float) -90.0;
- if (ndel_x < 0.0)
- *(data + i) = (float) 90.0;
- }
- }
- else if (cur_slp < 0.0) {
- if (del_x > 0.0) {
- if (ndel_x > 0.0)
- *(data + i) = (float) -90.0;
- if (ndel_x < 0.0)
- *(data + i) = (float) 90.0;
- }
- else if (del_x < 0.0) {
- if (ndel_x > 0.0)
- *(data + i) = (float) 90.0;
- if (ndel_x < 0.0)
- *(data + i) = (float) -90.0;
- }
- }
- }
- else {
- cur_th = slp_to_angle (cur_slp, del_x, del_y);
- next_th = slp_to_angle (next_slp, ndel_x, ndel_y);
- del_th = next_th - cur_th;
- #ifdef SHOW_ANG
- printf (" th: %5.2lf nth: %5.2lf d_th: %5.2lf",
- cur_th, next_th, del_th);
- #endif
-
- if (del_th > PI)
- del_th = -(2.0 * PI - del_th);
- if (del_th < -PI)
- del_th = 2.0 * PI + del_th;
-
- *(data + i) = (float) ((del_th * 180.0) / PI);
-
- #ifdef SHOW_ANG
- printf (" d_th(deg): %5.2f\n", *(data + i));
- #endif
- }
- cur_ln_ind = next_ln_ind;
- i++;
- }
- i++;
- } while (i < n_segm);
- }
-
-
- printf ("\n...sorting and constructing histogram\n");
- #if defined(LINUX)
- qsort (data, n_segm, sizeof (float), (__compar_fn_t) compare);
- #else
- qsort (data, n_segm, sizeof (float), compare);
- #endif
-
- #ifdef SHOW_SORT
- printf ("\n...sorted data:\n");
- for (i_sgl = 0; i_sgl < n_segm; i_sgl++)
- printf (" data[%d] = %f\n", i_sgl, *(data + i_sgl));
- #endif
-
- if (MIN_SET == 0)
- min = *(data + 0);
- if (MAX_SET == 0)
- max = *(data + n_segm - 1);
-
- mean = find_mean (data, n_segm);
- std_dev = find_sigma (data, n_segm, mean);
-
- bin_width = (max - min) / ((float) (N_BINS - 1));
- construct_hist (n_segm, data, hist, bin_width, min);
-
- printf ("\nhistogram:\n");
- printf ("......mean: %lf\n", mean);
- printf ("...std_dev: %lf\n", std_dev);
- printf ("...min: %f, bin_width: %f, max: %f\n", min, bin_width, max);
- for (i = 0; i < N_BINS; i++) {
- printf (" %6.2f", *(hist + i));
- if ((i + 1) % 10 == 0)
- printf ("\n");
- }
- fclose (fpIn);
-
- /*
- * ** write output file of type .hdt (see also: .adt, .pdt)
- */
- if (WRITE_FILE == 1) {
- fprintf (fpOut, "%d\n", N_BINS);
-
- for (i = 0; i < n_parms; i++)
- fprintf (fpOut, "%f\n", one);
-
- for (i = 0; i < N_BINS; i++)
- fprintf (fpOut, "%f %f\n", (float) i, *(hist + i));
-
- fclose (fpOut);
- }
-
-
- free (hist);
- free (inSegm);
- free (data);
- }
-